home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Texteditors / Origami / Sources / src / origami / virtual.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-27  |  18.1 KB  |  668 lines

  1. /*{{{}}}*/
  2. /*{{{  #includes*/
  3. #ifdef CONFIG_H
  4. #   include "config.h"
  5. #endif
  6.  
  7. #include <sys/types.h>
  8. #include <ctype.h>
  9. #include <string.h>
  10. #include <limits.h>
  11. #include <errno.h>
  12. #include <fcntl.h>
  13. #include <unistd.h>
  14. #include <stdlib.h>
  15. #include <stdio.h>
  16.  
  17. #define VIRTUAL_C
  18. #define I_LOOP_C
  19. #define I_FOLDING_C
  20. #define I_GETMSG_C
  21. #define I_MESSAGES_C
  22. #define I_ORIEDT_C
  23. #define I_SIGNALS_C
  24. #define I_STRING_C
  25.  
  26. #include "origami.h"
  27. #include <lib/ori_add_lib.h>
  28. /*}}}  */
  29.  
  30. /*{{{  #ifdef VIRTUAL - additional types,variables and procedures*/
  31. #ifdef VIRTUAL
  32.  
  33.   /*{{{  constants*/
  34. #  define LINE_PART             (BLOCK_SIZE-sizeof(off_t))
  35.                                /* number of chars, which can be stored   */
  36.                                /* in one fileblock                       */
  37.  
  38. #  define FILE_FREE_COUNT       (((int)(LINE_PART/sizeof(int)))-1)
  39.                                /* number of file-garbage-entries in a    */
  40.                                /* virtuell memoryblock (including a link */
  41.                                /* to next package)                       */
  42.   /*}}}  */
  43.   /*{{{  typedef VIR_ELEMENT*/
  44.   typedef struct
  45.    { element *parent;           /* textnode belonging to this textstring  */
  46.                                 /* nodes[0]: not used                     */
  47.    
  48.      int     pre,next;          /* links for doubled linked LRU-list      */
  49.                                 /* nodes[0]: pointer to head and tail of  */
  50.                                 /*           lru-list                     */
  51.    
  52.      int     filepo;            /* position of the unchanged text in file */
  53.                                 /* nodes[0]: list of free local buffers   */
  54.    
  55.      union
  56.       { unsigned char txt[LINELEN+1];
  57.                                 /* textline                               */
  58.         int *fre_f_buff;        /* pointer to list of free filebuffers    */
  59.                                 /* (used from nodes[0])                   */
  60.       } t;
  61.    
  62.    } VIR_ELEMENT;
  63.   /*}}}  */
  64.  
  65.   /*{{{  variables*/
  66.   private VIR_ELEMENT *nodes=0;       /* local buffers             */
  67.   private off_t old_pos=0;
  68.   private unsigned int file_used;     /* number of used fileblocks */
  69.   private int tmp_file;               /* file-descriptor for       */
  70.                                       /* temporary file            */
  71.   private int file_garbage;           /* index for handling free   */
  72.                                       /* file-blocks               */
  73.   private char ori_vir_tmp[_POSIX_PATH_MAX+1];
  74.                                       /* name of tmp-file          */
  75.   public int vir_nodes=0;             /* number of local buffers   */
  76.   /*}}}  */
  77.  
  78.   /*{{{  vir_dumb/vprint*/
  79. #  ifdef VIR_DEBUG
  80.      extern FILE *v_dumb;
  81.  
  82. #    define vprintf(f,x) (fprintf(v_dumb,f,x),fflush(v_dumb))
  83. #    define v_format "^^ %s ^^\n"
  84.      /*{{{  vir_dumb*/
  85.      private void vir_dumb(char*t)
  86.      { if (v_dumb)
  87.         { int i;
  88.  
  89.           for (i=0;i<vir_nodes;i++)
  90.            { fprintf(v_dumb,
  91.                      "%3d|node %p|f%3d|p%3d|n%3d|%.32s\n",
  92.                      i,
  93.                      (void*)nodes[i].parent,
  94.                      nodes[i].filepo,
  95.                      nodes[i].pre,
  96.                      nodes[i].next,
  97.                      i?nodes[i].t.txt:(unsigned char*)""
  98.                     );
  99.            }
  100.           vprintf(v_format,t);
  101.         }
  102.      }
  103.      /*}}}  */
  104. #  else
  105. #    define vir_dumb(x)
  106. #    define vprintf(f,x)
  107. #  endif
  108.   /*}}}  */
  109.  
  110.   /*{{{  v_error*/
  111.   private void v_error(char const*const s)
  112.   {
  113.     exit_origami(r_vir_err,get_msg(F_VM_FAIL,s,strerror(errno)));
  114.   }
  115.   /*}}}  */
  116.   /*{{{  handle the file-blocks, file-IO*/
  117.   /*{{{  seek_tmp              seek in tmp-file, arguments: offset*/
  118.   private void seek_tmp(off_t po)
  119.   { if (po!=old_pos && -1==(old_pos=lseek(tmp_file,po,SEEK_SET)))
  120.        v_error("seek");
  121.   }
  122.   /*}}}  */
  123.   /*{{{  read_tmp              read from tmp-file, arguments: offset,length,*data*/
  124.   private unsigned char *read_tmp(off_t po,int lg,unsigned char * const s)
  125.   { seek_tmp(po);
  126.     if (-1==read(tmp_file,(char *)s,lg))
  127.       v_error("read");
  128.     else
  129.       old_pos+=lg;
  130.  
  131.     return(s);
  132.   }
  133.   /*}}}  */
  134.   /*{{{  write_tmp             write to tmp-file, drguments: offset,length,*data*/
  135.   private void write_tmp(off_t po,int lg,unsigned char const * const s)
  136.   {
  137.     seek_tmp(po);
  138.     if (-1==write(tmp_file,(char *)s,lg))
  139.       v_error("write");
  140.     else
  141.       old_pos+=lg;
  142.   }
  143.   /*}}}  */
  144.  
  145.   /*{{{  get_file_buff         get a new file-block (or previously freed one)*/
  146.   private int get_file_buff(void)
  147.   {
  148.     int x;
  149.     int po;
  150.  
  151.     if (file_garbage) {
  152.      /*{{{  get fromlist*/
  153.      x=((int*) nodes[0].t.fre_f_buff)[--file_garbage];
  154.      /*{{{  if list now empty, try to get next part*/
  155.      if (!file_garbage) {
  156.        if ((po=((int*)nodes[0].t.fre_f_buff)[FILE_FREE_COUNT])) {
  157.          /*{{{  next-link was not 0!, so get the package*/
  158.          read_tmp((off_t)(po)*BLOCK_SIZE+sizeof(int),
  159.                   LINE_PART,
  160.                   (unsigned char*)nodes[0].t.fre_f_buff);
  161.          file_garbage=FILE_FREE_COUNT;
  162.          /*}}}  */
  163.        }
  164.      }
  165.      /*}}}  */
  166.      return(x);
  167.      /*}}}  */
  168.     } else {
  169.      /*{{{  new one*/
  170.      vprintf(v_format,"expand v-file");
  171.      /*{{{  clear the next-pointer in the block!*/
  172.      { int dummy=0;
  173.  
  174.        write_tmp((off_t)(++file_used)*BLOCK_SIZE,sizeof(off_t),(unsigned char*)&dummy);
  175.      }
  176.      vir_debug((off_t)(file_used*BLOCK_SIZE));
  177.      if (!file_used)
  178.         v_error("append");
  179.      /*}}}  */
  180.      return(file_used);
  181.      /*}}}  */
  182.     }
  183.   }
  184.   /*}}}  */
  185.   /*{{{  free_file_buff        add a file-block to garbage list*/
  186.   private void free_file_buff(int po)
  187.   {
  188.     /*{{{  if current block of garbage list full, save this part*/
  189.     if (file_garbage==FILE_FREE_COUNT) {
  190.       /*{{{  variables*/
  191.       int block_no;
  192.       /*}}}  */
  193.  
  194.       /*{{{  get number for the free-block in file*/
  195.       block_no= *(nodes[0].t.fre_f_buff);
  196.       /*}}}  */
  197.       write_tmp((off_t)block_no*BLOCK_SIZE+sizeof(int),
  198.                 LINE_PART,
  199.                 (unsigned char*) nodes[0].t.fre_f_buff);
  200.       nodes[0].t.fre_f_buff[FILE_FREE_COUNT]=block_no;
  201.       file_garbage=0;
  202.     }
  203.     /*}}}  */
  204.     /*{{{  move the free entry to list*/
  205.     nodes[0].t.fre_f_buff[file_garbage++]=po;
  206.     /*}}}  */
  207.  
  208.     return;
  209.   }
  210.   /*}}}  */
  211.   /*}}}  */
  212.   /*{{{  read/write data-lines*/
  213.   /*{{{  get_line_from_file    read a textline, argument: first block of line*/
  214.   private void get_line_from_file(int po,unsigned char * const txt)
  215.   {
  216.     /*{{{  variables*/
  217.     unsigned char *s=txt;
  218.     int next;
  219.     off_t current_po=(off_t)(po)*BLOCK_SIZE;
  220.     int lg=LINELEN;
  221.     /*}}}  */
  222.  
  223.     /*{{{  read the line to buff*/
  224.     do {
  225.       vprintf("%s","get line");
  226.       /*{{{  read the overflow-index*/
  227.       read_tmp(current_po,sizeof(off_t),(unsigned char*)&next);
  228.       /*}}}  */
  229.       /*{{{  read data*/
  230.       read_tmp(current_po+sizeof(off_t),LINE_PART<lg?LINE_PART:lg,s);
  231.       s+=LINE_PART;
  232.       lg-=LINE_PART;
  233.       /*}}}  */
  234.       current_po=(off_t)(next)*BLOCK_SIZE;
  235.     } while (next && lg>0);
  236.     *s='\0';
  237.     /*}}}  */
  238.   }
  239.   /*}}}  */
  240.   /*{{{  put_line_to_file      write a textline to file, return first block*/
  241.   private int put_line_to_file(unsigned char const * s)
  242.   {
  243.     /*{{{  variables*/
  244.     int po=get_file_buff();
  245.     off_t current_po=(off_t)(po)*BLOCK_SIZE;
  246.     int l=ustrlen(s);
  247.     int next;
  248.     /*}}}  */
  249.  
  250.     do {
  251.       /*{{{  write a part*/
  252.       /*{{{  get old overflow-index of the file-block*/
  253.       read_tmp(current_po,sizeof(off_t),(unsigned char*)&next);
  254.       /*}}}  */
  255.       l -= LINE_PART;
  256.       if (l>0) {
  257.         /*{{{  line must be splitted again*/
  258.         /*{{{  write the part*/
  259.         write_tmp(current_po+sizeof(off_t),LINE_PART,s);
  260.         s+=LINE_PART;
  261.         /*}}}  */
  262.         if (!next) {
  263.           /*{{{  get new overflow and store it in the fileblock too*/
  264.           next=get_file_buff();
  265.           write_tmp(current_po,sizeof(off_t),(unsigned char*)&next);
  266.           /*}}}  */
  267.         }
  268.         current_po = next*BLOCK_SIZE;
  269.         /*}}}  */
  270.       } else {
  271.         /*{{{  line is short enough for a packet*/
  272.         if (next) free_file_buff(next);
  273.         next=0;
  274.         write_tmp(current_po,sizeof(off_t),(unsigned char*)&next);
  275.         write_tmp(current_po+sizeof(off_t),l+LINE_PART+(l?1:0),s);
  276.         /*}}}  */
  277.       }
  278.       /*}}}  */
  279.     } while (l>0);
  280.  
  281.     return(po);
  282.   }
  283.   /*}}}  */
  284.   /*}}}  */
  285.   /*{{{  handle the local buffer-nodes*/
  286.   /*{{{  lru_handle            move a local buffer to top of LRU-list*/
  287.   private void lru_handle(int i)
  288.   {
  289.     int n,p;
  290.  
  291.     nodes[p=nodes[i].pre].next=n=nodes[i].next;
  292.     nodes[n].pre=p;
  293.     nodes[i].pre=0;
  294.     nodes[nodes[i].next=nodes[0].next].pre=i;
  295.     nodes[0].next=i;
  296.   }
  297.   /*}}}  */
  298.   /*{{{  get_local_buff        return a free local buffer (maybe free one)*/
  299.   private int get_local_buff(void)
  300.   {
  301.     int i,x;
  302.     VIR_ELEMENT *x_ptr;
  303.  
  304.     /*{{{  x=free local-buffer-place,x_ptr=its adress*/
  305.     if ((x=nodes[0].filepo)) {
  306.       /*{{{  free list not empty*/
  307.       x_ptr= &nodes[x];
  308.       /*{{{  remove from free-list*/
  309.       nodes[0].filepo=nodes[x].filepo;
  310.       /*}}}  */
  311.       /*{{{  append to head of lru*/
  312.       nodes[x_ptr->next=nodes[0].next].pre=x;
  313.       x_ptr->pre=0;
  314.       nodes[0].next=x;
  315.       /*}}}  */
  316.       /*}}}  */
  317.     } else {
  318.       /*{{{  make a place free*/
  319.       /*{{{  get a good place to move to file*/
  320.       x=nodes[0].pre;
  321.       /*{{{  not unchanged, so unchange all not fixed buffers*/
  322.       if (!nodes[x].filepo) {
  323.         for (i=((vir_nodes-FIXED-1)>>1)+1;i--;)
  324.          { if (!nodes[x].filepo)
  325.               nodes[x].filepo=put_line_to_file(nodes[x].t.txt);
  326.            x=nodes[x].pre;
  327.          }
  328.         x=nodes[0].pre;
  329.       }
  330.       /*}}}  */
  331.       x_ptr= &nodes[x];
  332.       /*}}}  */
  333.       /*{{{  set element's data-entry to file-block*/
  334.       x_ptr->parent->datas.posi=x_ptr->filepo;
  335.       /*}}}  */
  336.       lru_handle(x);
  337.       /*}}}  */
  338.     }
  339.     /*}}}  */
  340.     x_ptr->filepo=0;
  341.     vir_dumb("buff get local");
  342.  
  343.     return(x);
  344.   }
  345.   /*}}}  */
  346.   /*{{{  free_local_buff       add a local buffer to garbage-list*/
  347.   private void free_local_buff(int pos)
  348.   {
  349.     int p,n;
  350.     VIR_ELEMENT *current = &nodes[pos];
  351.  
  352.     /*{{{  if unchanged, free also the file-block*/
  353.     if (current->filepo) free_file_buff(current->filepo);
  354.     /*}}}  */
  355.     current->t.txt[0]='\0';
  356.     /*{{{  remove from LRU*/
  357.     nodes[p=current->pre].next=n=current->next;
  358.     nodes[n].pre=p;
  359.     /*}}}  */
  360.     /*{{{  put to free locals*/
  361.     current->filepo=nodes[0].filepo;
  362.     nodes[0].filepo=pos;
  363.     /*}}}  */
  364.     vir_dumb("buff free local");
  365.  
  366.     return;
  367.   }
  368.   /*}}}  */
  369.   /*}}}  */
  370.  
  371. #endif
  372. /*}}}  */
  373.  
  374. #ifdef VIRTUAL
  375.   /*{{{  init_data_handle      init the local buffer and the tmp-file*/
  376.   public int init_data_handle(void)
  377.   {
  378.     if (vir_nodes)
  379.      /*{{{  virtuell linehandling is active, initialise the buffers*/
  380.      { int i;
  381.        
  382.        /*{{{  minimum size of table is checked*/
  383.        if (vir_nodes<=FIXED)
  384.           vir_nodes=FIXED+1;
  385.        /*}}}  */
  386.        /*{{{  get the table*/
  387.        if (!(nodes=paket_malloc(vir_nodes*sizeof(VIR_ELEMENT)+LINE_PART)))
  388.           exit_origami(r_mem_full,M_NO_MEMORY);
  389.        /*}}}  */
  390.        /*{{{  init the table*/
  391.        /*{{{  normal nodes*/
  392.        for (i=vir_nodes-2;i;i--)
  393.           nodes[i].filepo=i+1;
  394.        nodes[vir_nodes-1].filepo=0;
  395.        /*}}}  */
  396.        /*{{{  root-node*/
  397.        nodes[0].pre=0;
  398.        nodes[0].next=0;
  399.        nodes[0].filepo=1;
  400.        nodes[0].t.fre_f_buff=(int*)&nodes[vir_nodes];
  401.        nodes[0].t.fre_f_buff[FILE_FREE_COUNT]=0;
  402.        /*}}}  */
  403.        /*}}}  */
  404.        file_garbage=0;
  405.        file_used=0;
  406.        /*{{{  open the tmp-file and set to position BLOCK_SIZE*/
  407.        tmpnam(ori_vir_tmp);
  408.        if ((tmp_file=open(ori_vir_tmp,O_RDWR | O_CREAT,0600))<0)
  409.           return(1);
  410.        if (-1==(old_pos=lseek(tmp_file,(off_t) BLOCK_SIZE,SEEK_SET)))
  411.           v_error("seek");
  412.        /*}}}  */
  413.        vir_dumb("start");
  414.      }
  415.      /*}}}  */
  416.     return(0);
  417.   }
  418.   /*}}}  */
  419.   /*{{{  end_data_handle       close and unlink tmp-file*/
  420.   public int end_data_handle(void)
  421.   {
  422.     return(vir_nodes && (close(tmp_file) || unlink(ori_vir_tmp)));
  423.   }
  424.   /*}}}  */
  425. #endif
  426.  
  427. /*{{{  get_data                get the data belonging to a node*/
  428. #ifdef VIRTUAL
  429.   public unsigned char *get_data(element const * const pin)
  430.   { element *p=(element*)pin;
  431.  
  432. #   ifdef VIRTUAL
  433.        if (vir_nodes)
  434.         /*{{{  virtuell linehandling is active*/
  435.         { int i,po;
  436.  
  437.           if ((i=p->datas.posi)==0)
  438.            /*{{{  empty string*/
  439.            { vprintf(v_format,"get empty");
  440.              
  441.              return((unsigned char*)empty_text);
  442.            }
  443.            /*}}}  */
  444.           else if (i==-vir_nodes)
  445.            /*{{{  short string*/
  446.            { vprintf(v_format,"get short");
  447.  
  448.              return(p->x.txt);
  449.            }
  450.            /*}}}  */
  451.           else if (i<0)
  452.            /*{{{  local buffer*/
  453.            { lru_handle(-i);
  454.              vir_dumb("get local");
  455.              
  456.              return(nodes[-i].t.txt);
  457.            }
  458.            /*}}}  */
  459.           else
  460.            /*{{{  get from file*/
  461.            { VIR_ELEMENT *cur;
  462.              
  463.              
  464.              p->datas.posi = -(po=get_local_buff());
  465.              cur = &nodes[po];
  466.              cur->parent=p;
  467.              cur->filepo=i;
  468.              get_line_from_file(i,cur->t.txt);
  469.              vir_dumb("get file");
  470.              
  471.              return(cur->t.txt);
  472.            }
  473.            /*}}}  */
  474.         }
  475.         /*}}}  */
  476. #   endif
  477.     return(p->datas.dat);
  478.   }
  479. #else
  480.   /* defined as a macro in origami.h */
  481. #endif
  482. /*}}}  */
  483. /*{{{  set_data                set the data of a node to new value*/
  484. public void set_data
  485.  ( element * const p,
  486.    unsigned char const * const s,
  487.    boolean const txt
  488.  )
  489. { int l;
  490.  
  491.   l=ustrlen(s);
  492. #ifdef VIRTUAL
  493.   if (vir_nodes)
  494.    /*{{{  virtuell line-handling is active*/
  495.    { int i,po;
  496.      
  497.      /*{{{  i= old position of text*/
  498.      i=p->datas.posi;
  499.      /*}}}  */
  500.      if (l>=sizeof(fold_data) || !txt)
  501.       /*{{{  new string must be stored extern (to long or fold))*/
  502.       { if (i<0 && i!=-vir_nodes)
  503.          /*{{{  old in buffer*/
  504.          { VIR_ELEMENT *current = &nodes[-i];
  505.            
  506.            /*{{{  free old data*/
  507.            if (current->filepo) free_file_buff(current->filepo);
  508.            /*}}}  */
  509.            ustrcpy(current->t.txt,s);
  510.            current->filepo=0;
  511.            lru_handle(-i);
  512.            vir_dumb("set buff text");
  513.          }
  514.          /*}}}  */
  515.         else
  516.          /*{{{  old in file or empty or short*/
  517.          {
  518.            /*{{{  maybe free the filedata*/
  519.            if (i>0) free_file_buff(i);
  520.            /*}}}  */
  521.            /*{{{  put data to new local buffer*/
  522.            p->datas.posi = -(po=get_local_buff());
  523.            { VIR_ELEMENT *current = &nodes[po];
  524.  
  525.              current->parent=p;
  526.              ustrcpy(current->t.txt,s);
  527.              current->filepo=0;
  528.            }
  529.            /*}}}  */
  530.            vir_dumb("set file/empty text");
  531.          }
  532.          /*}}}  */
  533.       }
  534.       /*}}}  */
  535.      else
  536.       /*{{{  new string short enough, to be stored in the node*/
  537.       {
  538. #        ifdef VIR_DEBUG
  539.            char *du;
  540. #        endif
  541.         
  542.         /*{{{  handle old data*/
  543.         if (i==0 || i==-vir_nodes)
  544.          /*{{{  ok, both in node*/
  545.          {
  546. #           ifdef VIR_DEBUG
  547.               du=l?"set empty/short short":"set empty/short empty";
  548. #           endif
  549.          }
  550.          /*}}}  */
  551.         else if (i<0)
  552.          /*{{{  local, free the local buffer*/
  553.          { free_local_buff(-i);
  554. #           ifdef VIR_DEBUG
  555.               du=l?"set local short":"set local empty";
  556. #           endif
  557.          }
  558.          /*}}}  */
  559.         else
  560.          /*{{{  in file, free the filebuffer*/
  561.          { free_file_buff(i);
  562. #           ifdef VIR_DEBUG
  563.               du=l?"set file short":"set file empty";
  564. #           endif
  565.          }
  566.          /*}}}  */
  567.         /*}}}  */
  568.         /*{{{  set new data*/
  569.         if (l)
  570.          /*{{{  copy to node*/
  571.          { p->datas.posi= -vir_nodes;
  572.            ustrcpy(p->x.txt,s);
  573.          }
  574.          /*}}}  */
  575.         else
  576.          /*{{{  mark empty*/
  577.          { p->datas.posi=0;
  578.          }
  579.          /*}}}  */
  580.         /*}}}  */
  581.         vprintf(v_format,du);
  582.       }
  583.       /*}}}  */
  584.    }
  585.    /*}}}  */
  586.   else
  587. #endif
  588.    /*{{{  memory*/
  589.    { unsigned char *to_free;
  590.  
  591.      /*{{{  store, if any memory to free (don't free, maybe new is part of old!)*/
  592.      to_free=p->datas.dat;
  593.      if (to_free==empty_text || to_free==p->x.txt)
  594.         to_free=0;
  595.      /*}}}  */
  596.      if (l)
  597.       /*{{{  new string is not empty, malloc and copy*/
  598.       { if
  599.          (    txt
  600.            && l<sizeof(fold_data)
  601.            && (    (    bd.m.select_mode!=fold_selection
  602.                      && bd.m.select_mode!=unmark_fold_selection
  603.                    )
  604.                 || p!=bd.f.select_ptr
  605.               )
  606.          )
  607.            p->datas.dat=p->x.txt;
  608.         else
  609.            if (!(p->datas.dat=ori_malloc(l+1)))
  610.               exit_origami(r_mem_full,M_NO_MEMORY);
  611.         ustrcpy(p->datas.dat,s);
  612.       }
  613.       /*}}}  */
  614.      else
  615.       /*{{{  empty text, use default empty-text-pointer*/
  616.         p->datas.dat=(unsigned char*)empty_text;
  617.       /*}}}  */
  618.      if (to_free)
  619.         paket_free(to_free);
  620.    }
  621.    /*}}}  */
  622. }
  623. /*}}}  */
  624. /*{{{  set_0_data              set the data of a node to empty*/
  625. public void set_0_data(element * const p)
  626. {
  627.  
  628. #ifdef VIRTUAL
  629.   if (vir_nodes)
  630.      set_data(p,empty_text,False);
  631.   else
  632. #endif
  633.    /*{{{  memory*/
  634.    { if (p->datas.dat!=empty_text && p->datas.dat!=p->x.txt)
  635.         paket_free(p->datas.dat);
  636.      p->datas.dat=(unsigned char*)empty_text;
  637.    }
  638.    /*}}}  */
  639. }
  640. /*}}}  */
  641. /*{{{  new_data                create empty data for a new malloced node*/
  642. #ifdef VIRTUAL
  643.   /*{{{  comment*/
  644.   /* new_data can be used more than once for the same node                 */
  645.   /* only if set-data is used for a node, a call of new_data will destroy  */
  646.   /* the garbage-collection-data.                                          */
  647.   /*}}}  */
  648.   public void new_data(element *p)
  649.   {
  650. #  ifdef VIRTUAL
  651.      if (vir_nodes)
  652.       /*{{{  virtual*/
  653.       { p->datas.posi=0;
  654.  
  655.         vprintf(v_format,"new");
  656.       }
  657.       /*}}}  */
  658.      else
  659. #  endif
  660.       /*{{{  memory*/
  661.         p->datas.dat=(unsigned char*)empty_text;
  662.       /*}}}  */
  663.   }
  664. #else
  665.   /* defined as a macro in origami.h */
  666. #endif
  667. /*}}}  */
  668.